﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace MiniBotControlLibSample
{

    /// <summary>
    /// 关节模块下位机通信接口
    /// </summary>
    public static class MiniBotControlLib
    {
        /// <summary>
        /// 设置接收数据超时时间
        /// </summary>
        /// <param name="nNetTimeout"></param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetRecvTimeOut(int nNetTimeout);

        #region 机器人连接通信

        /// <summary>
        /// 扫描在线机器人设备
        /// </summary>
        /// <param name="ips"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public extern unsafe static int ScanRobots(out IntPtr ips, ref int count);

        /// <summary>
        /// 连接目标机器人设备
        /// </summary>
        /// <param name="ip">目标机器人的IP地址（或串口名称），Ap模式默认是 10.10.100.254（默认串口为：/dev/minibot）</param>
        /// <param name="port">目标地址端口（默认为8899）,连接串口时为任意值</param>
        /// <returns>大于0：连接成功  0：连接失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int Connect(string ip, int port);

        /// <summary>
        /// 连接机器人（带超时设置）
        /// </summary>
        /// <param name="ip">目标机器人的IP地址（或串口名称），Ap模式默认是 10.10.100.254（默认串口为：/dev/minibot）</param>
        /// <param name="port">目标地址端口（默认为8899）,连接串口时为任意值</param>
        /// <param name="timeout">超时时间单位毫秒</param>
        /// <returns>大于0：连接成功  0：连接失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int ConnectWitchTimeOut([MarshalAs(UnmanagedType.LPWStr)] string ip, int port, int timeout);

        /// <summary>
        /// 断开目标机器人设备
        /// </summary>
        /// <returns>大于0：断开成功  0：断开失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int Disconnect();

        /// <summary>
        /// 扫描机器人底座连接的所有模块ID
        /// 备注：模块出厂ID预设值I:20-29;T:30-39;G:40-49
        /// </summary>
        /// <param name="startId">扫描范围的起始ID</param>
        /// <param name="endId">扫描范围的结束ID</param>
        /// <param name="id">扫描结果的Id数组</param>
        /// <param name="position">扫描结果的位置（串口）数组</param>
        /// <returns>扫描结果的数组长度</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public extern unsafe static int ScanId(byte startId, byte endId, IntPtr id, IntPtr position);

        #endregion

        #region 关节模块控制

        /// <summary>
        /// 获取指定ID关节模块的位置角度值
        /// </summary>
        /// <param name="id">需要获取的关节模块Id值</param>
        /// <returns>关节模块的位置单位为角度（一般返回值为：I:-180 到 180 ；T： - 90到90；G：0到90）</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int GetPosition(byte id);

        /// <summary>
        /// 获取指定ID关节模块的速度信息-【关节模块处于速度模式】
        /// </summary>
        /// <param name="id">需要获取的关节Id值</param>
        /// <returns>关节的位置速度单位：单位时间（每秒）内运动的步数，50步 / 秒 = 0.732 RPM(圈每分钟）</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int GetRunningSpeed(byte id);

        /// <summary>
        /// 获取指定ID关节模块的速度信息-【关节处于位置模式】
        /// </summary>
        /// <param name="id">需要获取的关节模块Id值</param>
        /// <returns>关节模块的位置速度单位：单位时间（每秒）内运动的步数，50步 / 秒 = 0.732 RPM(圈每分钟）</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int GetPositionSpeed(byte id);

        /// <summary>
        /// 设置关节模块位置角度（位置模式）
        /// </summary>
        /// <param name="id">需要设置的关节模块Id值</param>
        /// <param name="angle">角度值</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetPosition(byte id, double angle);

        /// <summary>
        /// 设置关节模块以指定速度运行到指定位置角度
        /// </summary>
        /// <param name="id">需要设置的关节模块Id值</param>
        /// <param name="angle">角度值</param>
        /// <param name="speed">速度百份比 如100即为最大速度</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetPositionWithSpeed(byte id, double angle, int speed);

        /// <summary>
        /// 设置指定ID关节模块的运行速度，会自动将关节模块设置为速度模式。该设置仅对I模块有效
        /// </summary>
        /// <param name="id">需要设置的I关节模块Id值(20-29的ID段)</param>
        /// <param name="speed">速度百份比 如100即为最大速度</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetRunningSpeed(byte id, int speed);

        /// <summary>
        /// 设置关节模块运行到指定角度的速度
        /// </summary>
        /// <param name="id">需要设置的关节Id值</param>
        /// <param name="speed">速度百份比 如100即为最大速度</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetPositionSpeed(byte id, int speed);

        /// <summary>
        /// 设置指定ID关节是否使能
        /// </summary>
        /// <param name="id">需要设置的关节Id值</param>
        /// <param name="isEnable">true开启；false 关闭</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int EnableTorque(byte id, bool isEnable);

        /// <summary>
        /// 设置关节模块模式
        /// </summary>
        /// <param name="id">需要设置的关节Id值</param>
        /// <param name="mode">0:位置模式；1:速度模式；2:PWM开环调速度模式；</param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotorMode(byte id, int mode);

        /// <summary>
        /// 同步设置多个关节模块的位置
        /// </summary>
        /// <param name="id">待设置的id数组</param>
        /// <param name="angle">待设置的角度数组</param>
        /// <param name="count">数组长度</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetPositionSync(byte[] id, double[] angle, int count);

        /// <summary>
        /// 设置模块的ID，设置的ID应满足以下ID段，否则使用时可能会造成硬件损伤
        /// </summary>
        /// <param name="oldId">当前要设置的目标模块ID</param>
        /// <param name="newId">要设置的新ID</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotoId(byte oldId, byte newId);

        /// <summary>
        /// 设置模块是否锁定不可写
        /// </summary>
        /// <param name="id">当前要设置的目标模块ID</param>
        /// <param name="isLock">是否锁定</param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotorLocked(byte id, bool isLock);

        #endregion

        #region 控制器配置

        /// <summary>
        /// 设置当前连接的机器人设备的连接模式为STA模式，即连接到公网WIFI热点 注：不支持5G网络
        /// </summary>
        /// <param name="ssid">Wifi热点的SSID</param>
        /// <param name="pwd">Wifi热点的密码</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetSTAMode(string ssid, string pwd);

        /// <summary>
        /// 设置当前连接的机器人设备的连接模式为AP模式，即将当前设备设置为可连接的热点
        /// </summary>
        /// <param name="ssid">Ap名称</param>
        /// <param name="pwd">Ap密码</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetAPMode(string ssid, string pwd);

        /// <summary>
        /// 设置小移动平台灯带模式（如果存在）
        /// </summary>
        /// <param name="val">0x01: 左转灯光 0x02：右转灯光 0x03：报警灯光 0x05：流水灯灯光（初始化默认是这个）</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetLEDBel(int val);

        #endregion

        #region 传感器通信接口
        /// <summary>
        /// 发布传感器数据-未公开
        /// </summary>
        /// <param name="type"></param>
        /// <param name="parameters"></param>
        /// <param name="count"></param>
        /// <param name="outParameters"></param>
        /// <param name="outCount"></param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SendSerialVal(byte type, byte[] parameters, int count, out byte[] outParameters, out int outCount);

        /// <summary>
        /// 读取外部设备数据(需连接传感器模块)
        /// </summary>
        /// <param name="id">传感器ID</param>
        /// <param name="ioPort">对应的IO口</param>
        /// <returns>大于0：获取成功  0：获取失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int GetDevData(byte id, byte ioPort);

        /// <summary>
        /// 设置传感器数据
        /// </summary>
        /// <param name="id">传感器ID</param>
        /// <param name="ioPort">对应的IO口或使能</param>
        /// <param name="data">待设置的数据数组</param>
        /// <param name="dataLen">待设置的数据数组的长度</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetDevData(byte id, byte ioPort, byte[] data, int dataLen);

        /// <summary>
        /// 从数据缓冲区中读取设备数据（例如：红外按钮）
        /// </summary>
        /// <param name="id">传感器ID（参考2.23）</param>
        /// <param name="ioPort">对应的IO口（参考2.23）</param>
        /// <returns>对应的值</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int ReadDevData(byte id, byte ioPort);

        #endregion

        #region 关节模块配置

        /// <summary>
        /// 设置模块高压保护值
        /// </summary>
        /// <param name="id">要设置的模块ID</param>
        /// <param name="value">电压值，单位为 0.1V。如参数为90 时则为 9V。硬件初始值为9V</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotoHighVoltageProtection(byte id, byte value);

        /// <summary>
        /// 设置模块低压保护值
        /// </summary>
        /// <param name="id">要设置的模块ID</param>
        /// <param name="value">电压值，单位为 0.1V。如参数为90 时则为 9V。硬件初始值为4V</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotoLowVoltageProtection(byte id, byte value);

        /// <summary>
        /// 设置模块的最大角度限制
        /// </summary>
        /// <param name="id">要设置的模块ID</param>
        /// <param name="angle">角度值，单位为角度. 最大值为360，最小值为0；180度为对应的关节的零位</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotoMaxAngle(byte id, int angle);

        /// <summary>
        /// 设置模块的最小角度限制
        /// </summary>
        /// <param name="id">要设置的模块ID</param>
        /// <param name="angle">角度值，单位为角度. 最大值为360，最小值为0, 180度为对应的关节的零位</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetMotoMinAngle(byte id, int angle);

        /// <summary>
        /// 未公开
        /// </summary>
        /// <param name="id"></param>
        /// <param name="stepOffset"></param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetPosZero(byte id, int stepOffset);

        /// <summary>
        /// 未公开
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]

        public static extern int GetPositionStep(byte id);

        /// <summary>
        /// 未公开
        /// </summary>
        /// <param name="id"></param>
        /// <param name="address"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int GetParameters(byte id, byte address, byte size);

        /// <summary>
        /// 设置PWM(运行时间)
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="value">值的正负表示方向，绝对值最小值为5，最大值为100</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetPWM(byte id, int value);

        /// <summary>
        ///获取PWM(运行时间)
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="pwm">返回值的指针 ，*pwm为对应获取的值（值的正负表示方向，绝对值最小值为5，最大值为100）</param>
        /// <returns>大于0：获取成功  0：获取失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int GetPWM(byte id, out int pwm);

        /// <summary>
        /// 设置位置环P 比例系数
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="value">目标值</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetRingP(byte id, byte value);

        /// <summary>
        /// 设置位置环D 微分系数
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="value">目标值</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetRingD(byte id, byte value);

        /// <summary>
        /// 设置位置环I 积分系数
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="value">目标值</param>
        /// <returns>大于0：设置成功  0：设置失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetRingI(byte id, byte value);

        /// <summary>
        /// 设置卸载条件
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="isVoltage">是否启用电压保护</param>
        /// <param name="isSensor">是否用启传感器保护</param>
        /// <param name="isTemperature">是否启用温度保护</param>
        /// <param name="isElectricity">是否启用电流保护</param>
        /// <param name="isAngle">是否启用角度保护</param>
        /// <param name="isOverload">是否启用过载保护</param>
        /// <returns>大于0：获取成功  0：获取失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetProtectConditions(byte id, bool isVoltage, bool isSensor, bool isTemperature, bool isElectricity, bool isAngle, bool isOverload);

        /// <summary>
        /// 设置LED报警条件
        /// </summary>
        /// <param name="id">模块ID</param>
        /// <param name="isVoltage">是否启用电压LED报警</param>
        /// <param name="isSensor">是否启用传感器LED报警</param>
        /// <param name="isTemperature">是否启用温度LED报警</param>
        /// <param name="isElectricity">是否启用电流LED报警</param>
        /// <param name="isAngle">是否启用角度LED报警</param>
        /// <param name="isOverload">是否启用过载LED报警</param>
        /// <returns>大于0：获取成功  0：获取失败</returns>
        [DllImport("MiniBotControlLib", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
        public static extern int SetLedConditions(byte id, bool isVoltage, bool isSensor, bool isTemperature, bool isElectricity, bool isAngle, bool isOverload);

        #endregion
    }
}
